﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Windows.Foundation;
using Windows.Graphics.Display;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Thirteen23.TED.Data;
using Thirteen23.TED.Models;

namespace Thirteen23.TED.Views
{
    public sealed partial class HomePage
    {
        public IEnumerable<TedTalk> Talks { get; set; }

        public HomePage()
        {
            InitializeComponent();
        }

        private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.ItemGridView.SelectedItem is TedTalk)
            {
                ApplicationModel.Instance.MainPage.NavigationFrame.Navigate(typeof(TalkPage).ToString(), this.ItemGridView.SelectedItem);
            }
        }

        private DisplayPropertiesEventHandler _displayHandler;
        private TypedEventHandler<ApplicationLayout, ApplicationLayoutChangedEventArgs> _layoutHandler;

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            if (_displayHandler == null)
            {
                _displayHandler = Page_OrientationChanged;
                _layoutHandler = Page_LayoutChanged;
            }
            DisplayProperties.OrientationChanged += _displayHandler;
            ApplicationLayout.GetForCurrentView().LayoutChanged += _layoutHandler;
            SetCurrentViewState(this);

            this.Sort.SelectionChanged += OnSortSelectionChanged;

            VisualStateManager.GoToState(this, "Loading", true);

            TedTalksModel.Instance.LoadTalksAsync().ContinueWith(t =>
                {
                    this.Dispatcher.Invoke(CoreDispatcherPriority.Normal, (obj, invokedArgs) =>
                    {
                        VisualStateManager.GoToState(this, "NotLoading", true);

                        Talks = TedTalksModel.Instance.Talks;
                        this.ItemGridView.ItemsSource = GetGroupedList(this.Sort.SelectedIndex);

                        UpdatePaging();
                    }, this, null);
                });
        }

        private void OnUnloaded(object sender, RoutedEventArgs e)
        {
            DisplayProperties.OrientationChanged -= _displayHandler;
            ApplicationLayout.GetForCurrentView().LayoutChanged -= _layoutHandler;

            this.Sort.SelectionChanged -= OnSortSelectionChanged;
        }

        private void Page_LayoutChanged(object sender, ApplicationLayoutChangedEventArgs e)
        {
            SetCurrentViewState(this);
        }

        private void Page_OrientationChanged(object sender)
        {
            SetCurrentViewState(this);
        }

        private void SetCurrentViewState(Control viewStateAwareControl)
        {
            VisualStateManager.GoToState(viewStateAwareControl, this.GetViewState(), false);
        }

        private String GetViewState()
        {
            var orientation = DisplayProperties.CurrentOrientation;
            if (orientation == DisplayOrientations.Portrait ||
                orientation == DisplayOrientations.PortraitFlipped) return "Portrait";
            var layout = ApplicationLayout.Value;
            if (layout == ApplicationLayoutState.Filled) return "Fill";
            if (layout == ApplicationLayoutState.Snapped) return "Snapped";
            return "Full";
        }

        private void OnSortSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.ItemGridView.ItemsSource = GetGroupedList(this.Sort.SelectedIndex);
        }

        private void UpdatePaging()
        {
            this.PagingText.Visibility = Windows.UI.Xaml.Visibility.Visible;

            this.TotalCount.Text = TedTalksModel.Instance.Talks.Count.ToString();

            var columns = (int)Math.Floor(this.ItemGridView.ActualWidth / 268);
            var rows = (int)Math.Floor(this.ItemGridView.ActualHeight / 276);

            this.CurrentPagingSet.Text = (columns * rows).ToString();
        }

        /// <summary>
        /// Algorithm to add starting tiles to a sorted section
        /// </summary>
        /// <param name="sortIndex"></param>
        /// <returns></returns>
        private IEnumerable<object> GetGroupedList(int sortIndex)
        {
            List<object> list = new List<object>();
            int month = -1;
            int letter = -1;

            IEnumerable<TedTalk> sortedList = null;
            switch (sortIndex)
            {
                case 0:
                    sortedList = this.Talks.OrderBy(t => t.Date);
                    break;
                case 1:
                    sortedList = this.Talks.OrderBy(t => t.SanitizedTitle);
                    break;
                case 2:
                    sortedList = this.Talks.OrderBy(t => t.Author);
                    break;
            }

            foreach (var talk in sortedList)
            {
                switch (sortIndex)
                {
                    case 0:
                        if (month == -1 || month != talk.Date.Month)
                        {
                            month = talk.Date.Month;
                            list.Add(new DateTile() { Date = talk.Date });
                        }
                        break;
                    case 1:
                        int currentTitleLetter = (int)talk.SanitizedTitle.ToLower()[0];
                        if (letter == -1 || letter != currentTitleLetter)
                        {
                            letter = currentTitleLetter;
                            list.Add(new DateTile() { Letter = Convert.ToChar(letter).ToString().ToUpper() });
                        }
                        break;
                    case 2:
                        int currentAuthorLetter = (int)talk.Author.ToLower()[0];
                        if (letter == -1 || letter != currentAuthorLetter)
                        {
                            letter = currentAuthorLetter;
                            list.Add(new DateTile() { Letter = Convert.ToChar(letter).ToString().ToUpper() });
                        }
                        break;
                }

                list.Add(talk);
            }
            
            return list;
        }
    }
}
